/**
  ******************************************************************************
  * @file    main.c
  * @author  ashuai0110
  * @version V2.0
  * @date    2024-09-09
  * @brief   使用举例-MODBUS主机程序
  *
  ******************************************************************************
  * @attention
  *
  * 版权声明:内容为编者(ashuai0110)原创,使用请注明出处,当然,你也可以不这样做^_^
  * 出处链接:https://gitee.com/ashuai0110/mcu_reuse_development_module
  *
  ******************************************************************************
  */

/* 包含头文件-----------------------------------------------------------------*/
#include "bsp.h"

#include "modbus_host.h"

/* 私有宏定义-----------------------------------------------------------------*/

/* 私有类型定义---------------------------------------------------------------*/

/* 私有变量-------------------------------------------------------------------*/
/* modbus错误信息 */
const static char *modbusErrorStr[] = {
    "response message length error!",
    "response message check error!",
    "response message frame error!",
};

static uint8_t modbusBuf[MB_BUF_SIZE_MAX]; /* modbus所需缓存区 */
static mb_host_t testMBH; /* modbus主机实例 */

/* 全局变量-------------------------------------------------------------------*/
/* 
注意:
本例应答处理中的线圈地址和寄存器地址均与本地线圈地址和本地寄存器地址一一对应,
若用户的存在偏移关系需自行修改添加.
*/
uint8_t coilStatus[8];       /* 线圈 共8*8=64个 地址0~63 */
uint8_t inputStatus[8];      /* 输入线圈 共8*8=64个 地址0~63 */
uint16_t holdingRegister[8]; /* 保持寄存器 共8*1=8个 地址0~7 */
uint16_t inputRegister[8];   /* 输入寄存器 共8*1=8个 地址0~7 */

/* 私有函数原型---------------------------------------------------------------*/


/**
  * @brief  This function handles SysTick Handler.
  *
  * @param  None
  *
  * @retval None
  */
void SysTick_Handler(void)
{
    /* 组件计时节拍接口 */
    mw_tick_inc(1);
}

/**
  * @brief  串口中断函数
  *
  * @param  None
  *
  * @retval None
  */
void USART1_IRQHandler(void)
{
    static uint8_t rxData, txData, ret;
    
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    {
        rxData = USART_ReceiveData(USART1);
        /* 写入接收缓存 */
        ret = mb_host_write_rx_buf(&testMBH, &rxData, 1);
        if(1 != ret)
        {
            MW_WARN_LOG("mb_host_write_rx_buf failure");
        }
        
        USART_ClearITPendingBit(USART1, USART_IT_RXNE);
    }
    
    if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)
    {
        /* 读出发送缓存 */
        ret = mb_host_read_tx_buf(&testMBH, &txData, 1);
        if(1 == ret)
        {
            USART_SendData(USART1, txData);
        }
        
        USART_ClearITPendingBit(USART1, USART_IT_TXE);
    }
}

/**
  * @brief  main
  */
int main(int argc, char *argv[])
{
    MW_VER_LOG("example-modbus_host", 2, 0, 0);
    
    /* BSP初始化 */
    bsp_init();
    
    /* modbus主机初始化 协议RTU 帧间隔超时100ms 应答超时500ms */
    mb_host_init(&testMBH, MB_RTU, modbusBuf, sizeof(modbusBuf), bsp_usart1_tx_en, 100, 500);
    
    /* 发送读取线圈命令 */
    mb_host_send_cmd(&testMBH, 0x1, 0x1, 0x0, 8, NULL);
    /* 发送读取离散输入命令 */
//    mb_host_send_cmd(&testMBH, 0x1, 0x2, 0x0, 8, NULL);
    /* 发送读取保持寄存器命令 */
//    mb_host_send_cmd(&testMBH, 0x1, 0x3, 0x0, 2, NULL);
    /* 发送读取输入寄存器命令 */
//    mb_host_send_cmd(&testMBH, 0x1, 0x4, 0x0, 2, NULL);
    
    /* 发送写入单个线圈命令 */
//    uint8_t coilVal = 1;
//    mb_host_send_cmd(&testMBH, 0x1, 0x5, 0x0, 0, &coilVal);
    /* 发送写入单个寄存器命令 */
//    uint16_t regVal = 0x1357;
//    mb_host_send_cmd(&testMBH, 0x1, 0x6, 0x0, 0, &regVal);
    /* 发送写入多个线圈命令 */
//    uint8_t coilVal[2] = {0xAA, 0xFF};
//    mb_host_send_cmd(&testMBH, 0x1, 0xF, 0x0, 10, &coilVal[0]);
    /* 发送写入多个寄存器命令 */
//    uint16_t regVal[2] = {0x1122, 0x5566};
//    mb_host_send_cmd(&testMBH, 0x1, 0x10, 0x0, 2, &regVal[0]);
    
    while(1)
    {
        uint8_t ret;
        /* modbus主机轮询处理 */
        ret = mb_host_poll(&testMBH);
        /* 处理中 */
        if(MW_RET_ING == ret)
        {
        } /* 应答处理完成 */
        else if(MW_RET_OK == ret)
        {
            MW_DEBUG_LOG("response success");
        } /* 应答超时 */
        else if(MW_RET_TIMEOUT == ret)
        {
            MW_WARN_LOG("response timeout");
        } /* 应答错误 */
        else
        {
            MW_ERROR_LOG("response error: %s", modbusErrorStr[ret - MW_RET_LEN_ERR]);
        }
    }
}

/* 此为弱定义函数的重定义 函数解释可在源码中查看 */
void mb_host_rsp_01h(mb_host_t *_mbh, uint16_t reg, uint16_t num, uint8_t *pData)
{
    int16_t numTmp;
    
    /* 判断实例 */
    if(_mbh == &testMBH)
    {
        MW_DEBUG_LOG("before-coilStatus: 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X", coilStatus[0], coilStatus[1], \
            coilStatus[2], coilStatus[3], coilStatus[4], coilStatus[5], coilStatus[6], coilStatus[7]);
        
        numTmp = num;
        while(0 < numTmp)
        {
            /* 设置线圈状态 */
            mb_set_bits(&coilStatus[0], reg, numTmp > 8 ? 8 : numTmp, *pData++);
            numTmp -= 8;
            reg += 8;
        }
        
        MW_DEBUG_LOG("after-coilStatus: 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X", coilStatus[0], coilStatus[1], \
            coilStatus[2], coilStatus[3], coilStatus[4], coilStatus[5], coilStatus[6], coilStatus[7]);
    }
}

/* 此为弱定义函数的重定义 函数解释可在源码中查看 */
void mb_host_rsp_02h(mb_host_t *_mbh, uint16_t reg, uint16_t num, uint8_t *pData)
{
    int16_t numTmp;
    
    /* 判断实例 */
    if(_mbh == &testMBH)
    {
        MW_DEBUG_LOG("before-inputStatus: 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X", inputStatus[0], inputStatus[1], \
            inputStatus[2], inputStatus[3], inputStatus[4], inputStatus[5], inputStatus[6], inputStatus[7]);
        
        numTmp = num;
        while(0 < numTmp)
        {
            /* 设置线圈状态 */
            mb_set_bits(&inputStatus[0], reg, numTmp > 8 ? 8 : numTmp, *pData++);
            numTmp -= 8;
            reg += 8;
        }
        
        MW_DEBUG_LOG("after-inputStatus: 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X", inputStatus[0], inputStatus[1], \
            inputStatus[2], inputStatus[3], inputStatus[4], inputStatus[5], inputStatus[6], inputStatus[7]);
    }
}

/* 此为弱定义函数的重定义 函数解释可在源码中查看 */
void mb_host_rsp_03h(mb_host_t *_mbh, uint16_t reg, uint16_t num, uint8_t *pData)
{
    /* 判断实例 */
    if(_mbh == &testMBH)
    {
        MW_DEBUG_LOG("before-holdingRegister: 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X", holdingRegister[0], holdingRegister[1], \
            holdingRegister[2], holdingRegister[3], holdingRegister[4], holdingRegister[5], holdingRegister[6], holdingRegister[7]);
        
        for(uint8_t i = 0; i < num; i++)
        {
            /* 设置寄存器值 */
            holdingRegister[reg + i] = (pData[i * 2] << 8) | pData[i * 2 + 1];
        }
        
        MW_DEBUG_LOG("after-holdingRegister: 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X", holdingRegister[0], holdingRegister[1], \
            holdingRegister[2], holdingRegister[3], holdingRegister[4], holdingRegister[5], holdingRegister[6], holdingRegister[7]);
    }
}

/* 此为弱定义函数的重定义 函数解释可在源码中查看 */
void mb_host_rsp_04h(mb_host_t *_mbh, uint16_t reg, uint16_t num, uint8_t *pData)
{
    /* 判断实例 */
    if(_mbh == &testMBH)
    {
        MW_DEBUG_LOG("before-inputRegister: 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X", inputRegister[0], inputRegister[1], \
            inputRegister[2], inputRegister[3], inputRegister[4], inputRegister[5], inputRegister[6], inputRegister[7]);
        
        for(uint8_t i = 0; i < num; i++)
        {
            /* 设置寄存器值 */
            inputRegister[reg + i] = (pData[i * 2] << 8) | pData[i * 2 + 1];
        }
        
        MW_DEBUG_LOG("after-inputRegister: 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X", inputRegister[0], inputRegister[1], \
            inputRegister[2], inputRegister[3], inputRegister[4], inputRegister[5], inputRegister[6], inputRegister[7]);
    }
}

/* 此为弱定义函数的重定义 函数解释可在源码中查看 */
void mb_host_rsp_05_10h(mb_host_t *_mbh)
{
    /* 判断实例 */
    if(_mbh == &testMBH)
    {
        MW_DEBUG_LOG("test modbus host: write data success");
    }
}

/* 此为弱定义函数的重定义 函数解释可在源码中查看 */
void mb_host_rsp_err(mb_host_t *_mbh, uint8_t *pData)
{
    /* 判断实例 */
    if(_mbh == &testMBH)
    {
        MW_DEBUG_LOG("test modbus host: errFunCode:0x%X, errCode:0x%X", pData[0], pData[1]);
    }
}
